package com.android.hidephotosplus.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.support.v4.util.LruCache;
import android.util.Log;
import android.widget.ImageView;

import com.android.hidephotosplus.R;

public class MLoadMedia {

	private LruCache<String, Bitmap> mBitmapCache;
	private ArrayList<String> mCurrentTasks;

	private int mMaxWidth;
	private int mMaxHeight;

	public MLoadMedia(int size, int maxWidth, int maxHeight) {
		mMaxWidth = maxWidth;
		mMaxHeight = maxHeight;

		mBitmapCache = new LruCache<String, Bitmap>(size) {
			@Override
			protected int sizeOf(String key, Bitmap b) {
				// Assuming that one pixel contains four bytes.
				return b.getHeight() * b.getWidth() * 4;
			}
		};
		mCurrentTasks = new ArrayList<String>();
	}

	private void addBitmapToCache(String key, Bitmap bitmap) {
		if (getBitmapFromCache(key) == null) {
			mBitmapCache.put(key, bitmap);
		}
	}

	private Bitmap getBitmapFromCache(String key) {
		return mBitmapCache.get(key);
	}

	/**
	 * Gets a bitmap from cache. <br/>
	 * <br/>
	 * If it is not in cache, this method will: <br/>
	 * <b>1:</b> check if the bitmap url is currently being processed in the
	 * BitmapLoaderTask and cancel if it is already in a task (a control to see
	 * if it's inside the currentTasks list). <br/>
	 * <b>2:</b> check if an internet connection is available and continue if
	 * so. <br/>
	 * <b>3:</b> download the bitmap, scale the bitmap if necessary and put it
	 * into the memory cache. <br/>
	 * <b>4:</b> Remove the bitmap url from the currentTasks list. <br/>
	 * <b>5:</b> Notify the ListAdapter.
	 * 
	 * @param mainActivity
	 *            - Reference to activity object, in order to call
	 *            notifyDataSetChanged() on the ListAdapter.
	 * @param imageKey
	 *            - The bitmap url (will be the key).
	 * @param imageView
	 *            - The ImageView that should get an available bitmap or a
	 *            placeholder image.
	 * @param isScrolling
	 *            - If set to true, we skip executing more tasks since the user
	 *            probably has flinged away the view.
	 */
	public void loadBitmap(Context context, boolean isVideo, String imageKey,
			ImageView imageView, boolean isScrolling, Runnable callback,
			boolean isPublic) {
		if (imageKey != null) {
			final Bitmap bitmap = getBitmapFromCache(imageKey);
			if (bitmap != null) {
	//			setImageBitmapWithFade(imageView, bitmap);
				imageView.setImageBitmap(bitmap);
			} else {
				if (isVideo)
					imageView.setImageResource(R.drawable.bg_action_bar);
				else
					imageView.setImageResource(R.drawable.bg_action_bar);
				if (!isScrolling && !mCurrentTasks.contains(imageKey)) {
					BitmapLoaderTask task = new BitmapLoaderTask(context,
							isVideo, imageKey, callback, isPublic);
					task.execute();
				}
			}
		}

	}

	// Effect
	public static void setImageBitmapWithFade(final ImageView imageView,
			final Bitmap bitmap) {
		Resources resources = imageView.getResources();
		BitmapDrawable bitmapDrawable = new BitmapDrawable(resources, bitmap);
		setImageDrawableWithFade(imageView, bitmapDrawable);
	}

	public static void setImageDrawableWithFade(final ImageView imageView,
			final Drawable drawable) {
		Drawable currentDrawable = imageView.getDrawable();
		if (currentDrawable != null) {
			Drawable[] arrayDrawable = new Drawable[2];
			arrayDrawable[0] = currentDrawable;
			arrayDrawable[1] = drawable;
			TransitionDrawable transitionDrawable = new TransitionDrawable(
					arrayDrawable);
			// transitionDrawable.setCrossFadeEnabled(true);
			imageView.setImageDrawable(transitionDrawable);
			transitionDrawable.startTransition(500);
		} else {
			imageView.setImageDrawable(drawable);
		}
	}

	private class BitmapLoaderTask extends AsyncTask<Void, Void, Bitmap> {
		private Runnable mCallback;
		private String mImageKey;
		private Context context;
		private boolean isVideo;
		private boolean isPublic;

		public BitmapLoaderTask(Context context, boolean isVideo,
				String imageKey, Runnable callback, boolean isPublic) {
			this.mImageKey = imageKey;
			this.mCallback = callback;
			this.context = context;
			this.isVideo = isVideo;
			this.isPublic = isPublic;
		}

		@Override
		protected void onPreExecute() {
			mCurrentTasks.add(mImageKey);
		}

		@Override
		protected Bitmap doInBackground(Void... params) {
			Bitmap bitmap = null;
			try {
				if (isVideo) {
					bitmap = BitmapUtils.createThumbnailVideos(mImageKey);
				} else {
					if (isPublic) {
						bitmap = BitmapUtils.getThumbnailByPath(
								context.getContentResolver(), mImageKey);
					} else {
						File thumb = new File(mImageKey
								+ Config.EXETENSION_THUMBNAIL);
						if (thumb.exists()) {
							bitmap = BitmapUtils.getThumbFromDisk(
									thumb.getAbsolutePath(),
									Config.MAX_PIXELS_WIDTH,
									Config.MAX_PIXELS_HEIGHT);
						} else {
							bitmap = BitmapUtils.getThumbFromDisk(mImageKey,
									mMaxWidth, mMaxHeight);
							if (bitmap != null) {
								FileOutputStream mStream;
								try {
									mStream = new FileOutputStream(thumb);
									bitmap.compress(Bitmap.CompressFormat.JPEG,
											100, mStream);
									mStream.flush();
									mStream.close();
								} catch (FileNotFoundException e1) {
									Log.e("FileNotFoundException",
											e1.toString());
									e1.printStackTrace();
								} catch (IOException e) {
									e.printStackTrace();
									Log.e("IOException", e.toString());
								}
							} else {
								mCurrentTasks.remove(mImageKey);
							}

						}

					}
				}

			} catch (Exception e) {
				e.printStackTrace();
				Log.e("Exception", e.toString());
			}
			if (bitmap != null) {
				addBitmapToCache(mImageKey, bitmap);
				return bitmap;
			}
			return null;
		}

		@Override
		protected void onPostExecute(Bitmap param) {
			mCurrentTasks.remove(mImageKey);
			if (param != null) {
				mCallback.run();
			}
		}
	}

}
